/**
 * 
 */
package GPIO;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;

/**
 * @author Jonas Spitzenpfeil
 * 
 */
public class GPIOControl {

	private static GpioController gpioController;
	private static GpioPinDigitalOutput[] gpioOutList = new GpioPinDigitalOutput[17];

	public static void initialize() {
		gpioController = GpioFactory.getInstance();

		gpioOutList[0] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_00, "PIN_00", PinState.LOW);
		gpioOutList[1] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_01, "PIN_01", PinState.LOW);
		gpioOutList[2] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_02, "PIN_02", PinState.LOW);
		gpioOutList[3] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_03, "PIN_03", PinState.LOW);
		gpioOutList[4] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_04, "PIN_04", PinState.LOW);
		gpioOutList[5] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_05, "PIN_05", PinState.LOW);
		gpioOutList[6] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_06, "PIN_06", PinState.LOW);
		gpioOutList[7] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_07, "PIN_07", PinState.LOW);
		gpioOutList[8] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_08, "PIN_08", PinState.LOW);
		gpioOutList[9] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_09, "PIN_09", PinState.LOW);
		gpioOutList[10] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_10, "PIN_10", PinState.LOW);
		gpioOutList[11] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_11, "PIN_11", PinState.LOW);
		gpioOutList[12] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_12, "PIN_12", PinState.LOW);
		gpioOutList[13] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_13, "PIN_13", PinState.LOW);
		gpioOutList[14] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_14, "PIN_14", PinState.LOW);
		gpioOutList[15] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_15, "PIN_15", PinState.LOW);
		gpioOutList[16] = gpioController.provisionDigitalOutputPin(
				RaspiPin.GPIO_16, "PIN_16", PinState.LOW);
	}

	/**
	 * Shutdown and closes the GPIO objects
	 */
	public static void shutdown() {
		for (GpioPinDigitalOutput out : gpioOutList) {
			out.low();
		}

		gpioController.shutdown();
	}

	/**
	 * @return The count of the available GPIO pins
	 */
	public static int getPinCount() {
		return gpioOutList.length;
	}

	/**
	 * Sets the out state of the given pin
	 * 
	 * @param pin
	 *            Minimum 0 and maximum 16
	 * @param on
	 *            The state to set to the pin
	 * @throws Exception
	 *             Is thrown when the pin is out of range
	 */
	public static void setPinOut(int pin, boolean on) throws Exception {
		if (pin < 0 || pin > 16) {
			throw new Exception("Invalid Pin: " + String.valueOf(pin));
		}

		if (on) {
			gpioOutList[pin].high();
		} else {
			gpioOutList[pin].low();
		}
	}

	/**
	 * Gets the out state of the given pin
	 * 
	 * @param pin
	 *            Minimum 0 and maximum 16
	 * @return The out state
	 */
	public static boolean getPinOut(int pin) {
		return ((gpioOutList[pin].getState() == PinState.HIGH) ? true : false);
	}
}
